package br.com.rookgraph;

public class BranchReducePlus extends BranchReduce {

	private BranchReducePlus(Graph original, Graph tree, boolean useIR) {
		super(original, tree, useIR);
	}

	public BranchReducePlus(Graph original, Graph tree) {
		this(original, tree, false);
	}

	@Override
	protected Edge selectCutEdge(Edge[] listCut) {

		Edge edgeCut = null;
		for (Edge candidate : listCut) {

			candidate.delta = getTree().delta(candidate, false);

			if (edgeCut == null || candidate.delta > edgeCut.delta) {

				edgeCut = candidate;

			} else if (candidate.delta == edgeCut.delta) {

				candidate.grauLeader = getTree().grauEdgeLeader(candidate, false);
				edgeCut.grauLeader = getTree().grauEdgeLeader(edgeCut, false);

				if (candidate.grauLeader < edgeCut.grauLeader) {

					edgeCut = candidate;

				}else if (candidate.grauLeader == edgeCut.grauLeader){

					candidate.sigma = getTree().sigma(candidate);
					edgeCut.sigma = getTree().sigma(edgeCut);

					if( candidate.sigma < edgeCut.sigma){

						edgeCut = candidate;

					}else if( candidate.sigma == edgeCut.sigma){

						candidate.sigma = getOriginal().sigma(candidate);
						edgeCut.sigma = getOriginal().sigma(edgeCut);

						if( candidate.sigma > edgeCut.sigma){

							edgeCut = candidate;
						}
					}
				}
			}
		}
		return edgeCut;
	}


	@Override
	protected Edge selectEdgeFromReplamentList(Edge[] listRep, Edge edgeCut) {

		Edge edgeRep = null;

		for (Edge candidate : listRep) {

// 1º Critério - Menor DELTA
			candidate.delta = getTree().delta(candidate, true);

			if (edgeRep == null || candidate.delta < edgeRep.delta) {

				edgeRep = candidate;
			}
		    else if (candidate.delta == edgeRep.delta) {

				candidate.grauLeader = getTree().grauEdgeLeader(candidate, true);
				edgeRep.grauLeader = getTree().grauEdgeLeader(edgeRep, true);

// 2º Critério - Maior Grau Lider
				if (candidate.grauLeader > edgeRep.grauLeader) {

					edgeRep = candidate;

				}else if (candidate.grauLeader == edgeRep.grauLeader){

					getTree().addEdge(candidate);

					candidate.sigma = getTree().sigma(candidate);
					edgeRep.sigma = getTree().sigma(edgeRep);

					getTree().removeEdge(candidate);

// 3º Critério - Maior SIGMA na árvore
					if (candidate.sigma > edgeRep.sigma){

						edgeRep = candidate;

					}else if( candidate.sigma == edgeRep.sigma){

						candidate.sigma = getOriginal().sigma(candidate);
						edgeRep.sigma = getOriginal().sigma(edgeRep);

// 4º Critério - Maior SIGMA no GRAFO
						if( candidate.sigma > edgeRep.sigma){
							edgeRep = candidate;
						}
					}
				}
			}
		}
		return edgeRep != null && isVantajoso(edgeRep, edgeCut)? edgeRep : null;
	}

	private boolean isVantajoso(Edge candidate, Edge edgeCut){

		if (candidate.delta < edgeCut.delta) {
			return true;
		}
		else if (candidate.delta == edgeCut.delta) {

			if (candidate.grauLeader > edgeCut.grauLeader) {
				return true;
			}else if (candidate.grauLeader == edgeCut.grauLeader){

				getTree().addEdge(candidate);

				candidate.sigma = getTree().sigma(candidate);
				edgeCut.sigma = getTree().sigma(edgeCut);

				getTree().removeEdge(candidate);

				if( candidate.sigma > edgeCut.sigma){

					return true;

				}else if( candidate.sigma == edgeCut.sigma){

					candidate.sigma = getOriginal().sigma(candidate);

					edgeCut.sigma = getOriginal().sigma(edgeCut);

					if( candidate.sigma > edgeCut.sigma){

						return true;
					}
				}
			}
		}
		return false;
	}
}
